﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using Fetches.Fetch.Dto;
using Fetches.Fetch.Factory;
using Fetches.Fetch.PagePool.Consume;
using Fetches.Fetch.Utils;
using RestSharp;
using Serilog;

namespace OrderSubmit
{
    /// <summary>
    /// 连接到远程主机的Factory类，可以是控制中心也可以是单独爬取部署单元
    /// </summary>
    public class RemoteFetchFactory : AbstractFetchFactory
    {
        protected RestClient _restClient;
        private FactoryConfig _factoryConfig;

        protected RemoteFetchFactory(string address)
        {
            _restClient = new RestClient(address);
            _factoryConfig = Get<FactoryConfig>("/system/factory_config");
        }

        protected override FetchReceipt ActuallyFetch(FetchOrder order)
        {
            var receipt = Post<FetchReceipt>("/fetch", order);
            Log.Information("order {@order} is submitted to RemoteFetchFactory {address},receipt is{@receipt}", order, _restClient.BaseUrl, receipt);
            return receipt;
        }

        /// <summary>
        /// 控制中心和单独爬取部署单元都有加减速api，只不过单独爬取部署单元对加减速实际无调整而已
        /// </summary>
        /// <param name="receipt"></param>
        /// <param name="fetchers2Hire"></param>
        public override void SpeedUpFetch(FetchReceipt receipt, int fetchers2Hire)
        {
            var result = Get<IList<long>>($"/fetch/speed_up/{receipt.Id}/{fetchers2Hire}");
            foreach (var id in result)
            {
                receipt.FetcherIds.Add(id);
            }
            Log.Information("task {receiptId} on RemoteFetchFactory {address} is speed down,current ids is {ids}", receipt.Id, _restClient.BaseUrl, receipt.FetcherIds);
        }

        public override void SpeedDownFetch(FetchReceipt receipt, int fetchers2Dismiss)
        {
            var result = Get<IList<long>>($"/fetch/speed_down/{receipt.Id}/{fetchers2Dismiss}");
            foreach (var id in result)
            {
                receipt.FetcherIds.Remove(id);
            }
            Log.Information("task {receiptId} on RemoteFetchFactory {address} is speedup,current ids is {ids}", receipt.Id, _restClient.BaseUrl, receipt.FetcherIds);
        }

        public override void StopFetch(FetchReceipt receipt)
        {
            Delete($"fetch/{receipt.Id}", null);
            Log.Information("asked RemoteFetchFactory {address} to stop fetch task {id}", receipt.Id, _restClient.BaseUrl);
        }
        public override void ContinueFetch(FetchReceipt receipt)
        {
            Post<string>($"fetch/{receipt.Id}", null);
            Log.Information("asked RemoteFetchFactory {address} to continue fetch task {id}", receipt.Id, _restClient.BaseUrl);
        }

        public override void Watch(FetchReceipt receipt, Action<FetchTaskProgress> progressAction)
        {
            new Thread(() =>
            {
                FetchTaskProgress progress;
                do
                {
                    progress = Get<FetchTaskProgress>($"/fetch/progress/{receipt.Id}");
                    progressAction?.Invoke(progress);
                    Thread.Sleep(5 * 1000);
                } while (progress.Status != FetchTaskStatus.Canceled && progress.Status != FetchTaskStatus.Solved);

            }).Start();
        }

        public override ProcessReceipt Process(ProcessOrder processOrder)
        {
            var receipt = Post<ProcessReceipt>("/process", processOrder);
            Log.Information("asked RemoteFetchFactory {address} to process {receipt} with {@processOrder},process id{processId}",
                _restClient.BaseUrl, processOrder.FetchReceiptId, processOrder, receipt.Id);
            return receipt;
        }

        #region 内部方法
        protected T Get<T>(string url)
        {
            var request = new RestRequest(url, DataFormat.Json);
            var response = _restClient.Get<T>(request);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                return response.Data;
            }

            return default(T);
        }

        protected T Post<T>(string url, object data)
        {
            var request = new RestRequest(url)
                .AddJsonBody(data);

            var response = _restClient.Post<T>(request);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                return response.Data;
            }

            return default(T);
        }
        protected void Delete(string url, object data)
        {
            var request = new RestRequest(url)
                .AddJsonBody(data);

            _restClient.Delete(request);
        }

        protected T Delete<T>(string url, object data)
        {
            var request = new RestRequest(url)
                .AddJsonBody(data);

            var response = _restClient.Delete<T>(request);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                return response.Data;
            }

            return default(T);
        }

        #endregion

        #region 数据加工
        public override PagePoolConsumer Consume(FetchReceipt receipt)
        {
            throw new NotImplementedException("远程主机的消费方式得有别的考量，客户端电脑不一定能连接到所有远程主机定义的组件");
            //Log.Information("process the fetched pages of fetch {id} from RemoteFetchFactory {address} ", receipt.Id, _restClient.BaseUrl);

            //var pool = _workshop.GetPagePool(receipt.Id).Result;
            //var coordinator = _workshop.GetProcessCoordinator(IdHelper.ProcessTaskIdGenerator.GenerateId()).Result;
            //var consumer = new PagePoolConsumer(pool, coordinator);

            //return consumer;
        }

        #endregion
    }
}
